package com.wtwd.campus.jdzc.controller;

import com.wtwd.campus.common.Constants;
import com.wtwd.campus.jdzc.common.Constant;
import com.wtwd.campus.jdzc.common.RespCode;
import com.wtwd.campus.jdzc.common.RespEntity;
import com.wtwd.campus.jdzc.entity.DeviceInfo;
import com.wtwd.campus.jdzc.service.AuthService;
import com.wtwd.campus.jdzc.service.JdzcDeviceInfoService;
import com.wtwd.campus.jdzc.service.JdzcLocationService;
import com.wtwd.campus.jdzc.service.JdzcStudentService;
import com.wtwd.campus.service.RedisService;
import com.wtwd.campus.utils.CommandSendUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author: ldaoliang
 * @DateTime: 2022/2/14 16:31
 * @Description:
 */
@RestController
@RequestMapping("/jdzc/location")
public class JdzcLocationController {


    private static final Logger logger = LoggerFactory.getLogger(JdzcLocationController.class);



    @Autowired
    private RedisService redisService;


    @Autowired
    private JdzcStudentService jdzcStudentService;

    @Autowired
    private JdzcLocationService jdzcLocationService;


    @Autowired
    private JdzcDeviceInfoService jdzcDeviceInfoService;

    @Autowired
    private CommandSendUtils commandSendUtils;

    @Autowired
    private AuthService authService;




    /**
     * 查询学生定位
     *
     * @param studentId
     * @param request
     * @return
     */
    @GetMapping("/queryStudentLocation/{studentId}")
    public RespEntity queryStudentLocation(@PathVariable("studentId") Integer studentId,
                                           HttpServletRequest request) {
        logger.info("queryStudentLocation : studentId = {},id = {}  " + studentId.toString());
        //获取用户id
        Integer userId = getUserId(request);
        if (userId == 0) {
            return new RespEntity(RespCode.TOKEN_UNAUTHORIZED);
        }
        //鉴别用户是否可操作该学生
        Boolean authStudent = authService.authStudent(studentId, Constant.jdzcOrgCode, userId);
        if (!authStudent){
            return new RespEntity(RespCode.NO_RIGHT_OPERATION);
        }
        //根据用户id查询绑定学生信息
        List<Map<String, Object>> studentList = jdzcStudentService.getStudentList(userId);
        if (studentList == null || studentList.size() == 0) {
            return new RespEntity(RespCode.USER_NO_BANDING_STUDENT);
        }
        List<Integer> stuIdList = new ArrayList<>();
        //判断查询单个学生还是所有学生
        if (studentId == 0) {
            //查询所有
            for (Map<String, Object> map : studentList) {
                if ((Integer) map.get("status") != Constants.WX_DEVICE_NOT_FOUND) {
                    stuIdList.add((Integer) map.get("student_id"));
                }
            }
        } else {
            stuIdList.add(studentId);
        }
        //根据学生id获取学生的最新定位信息
        List<Map<String, Object>> locationList = jdzcDeviceInfoService.getStudentPlaceByStudentId(stuIdList);
        if (locationList != null && locationList.size() != 0) {
            //判断当前学生设备是否在线
            for (Map<String, Object> map : locationList) {
                String imei = (String) map.get("imei");
                boolean b = deviceOnline(imei);
                map.put("isOnline", b ? "在线" : "离线");
            }
            //去重数据每个学生只能有一笔定位数据
            List<Optional<Map<String, Object>>> result = locationList.stream().collect(Collectors.groupingBy(e -> e.get("device_id"))).values().stream().map(e -> {
                return e.stream().max((s1, s2) -> (Integer) s1.get("id") > (Integer) s2.get("id") ? 1 : -1);
            }).collect(Collectors.toList());
            List<Map<String, Object>> resultList = new ArrayList<>();
            result.stream().forEach(e -> {
                resultList.add(e.get());
            });
            logger.info("/返回给前端数据：data={}", resultList.toString());
            return new RespEntity(RespCode.SUCCESS, resultList);
        }
        return new RespEntity(RespCode.SUCCESS, locationList);
    }


    /**
     * 获取设备的轨迹
     *
     * @param deviceId
     * @param request
     * @return
     */
    @GetMapping("/getAttackByDeviceId/{deviceId}/{time}")
    public RespEntity getAttackByDeviceId(@PathVariable("deviceId") Integer deviceId, @PathVariable("time") Long time,
                                          HttpServletRequest request) {
        logger.info("getAttackByDeviceId : deviceId = {},id = {}  " + deviceId.toString());
        //获取用户id
        Integer userId = getUserId(request);
        if (userId == 0) {
            return new RespEntity(RespCode.TOKEN_UNAUTHORIZED);
        }
        DeviceInfo deviceInfo = jdzcDeviceInfoService.getDeviceInfoByDeviceId(deviceId);
        //兼备设备是否可操作
        Boolean aBoolean = authService.authDevice(deviceInfo, Constant.jdzcOrgCode);
        if (!aBoolean){
            return new RespEntity(RespCode.NO_PERMISSION);
        }
        //根据设备id和时间获取设备当天的轨迹
        List<Map<String, Object>> trackList = jdzcLocationService.getDeviceTrackByDeviceIdWx(deviceId, time);
        //数据去重
        ArrayList<Map<String, Object>> result = trackList.stream().collect(Collectors.collectingAndThen(
                Collectors.toCollection(() -> new TreeSet<Map<String, Object>>(
                        Comparator.comparing(o -> (Integer) o.get("id")))), ArrayList::new));
   /*     //对轨迹数据进行处理筛选
        List<Map<String, Object>> list = dealLocation(result);*/
        if (result != null && result.size() != 0) {
            return new RespEntity(RespCode.SUCCESS, result);
        }
        return new RespEntity(RespCode.SUCCESS, result);
    }


    /**
     * 立即定位
     *
     * @param stuId
     * @param request
     * @return
     */
    @GetMapping("/getImmediatelyLocation/{stuId}")
    public RespEntity getImmediatelyLocation(@PathVariable("stuId") Integer stuId, HttpServletRequest request) {
        logger.info("getImmediatelyLocation : stuId = {}" + stuId.toString());
        String token = request.getHeader(Constant.HEADER_TOKEN_KEY);
        String redisUserId = redisService.getValue(token);
        if (StringUtils.isBlank(redisUserId)) {
            return new RespEntity(RespCode.TOKEN_UNAUTHORIZED);
        }
        Integer userId = Integer.parseInt(redisUserId);
        //鉴别该学生是否可操作
        Boolean authStudent = authService.authStudent(stuId, Constant.jdzcOrgCode, userId);
        if (!authStudent){
         return new RespEntity(RespCode.NO_PERMISSION);
        }
        List<Integer> stuIdList = new ArrayList<>();
        if (stuId == 0) {
            //给所有学生进行立即定位
            //根据用户id查询绑定学生信息
            List<Map<String, Object>> studentList = jdzcStudentService.getStudentList(userId);
            if (studentList == null || studentList.size() == 0) {
                return new RespEntity(RespCode.USER_NO_BANDING_STUDENT);
            }
            studentList.stream().forEach(e -> {
                stuIdList.add((Integer) e.get("student_id"));
            });
        } else {
            stuIdList.add(stuId);
        }
        //根据学生id获取设备imei
        List<String> imeiList = jdzcStudentService.getImeiListByStuIdList(stuIdList);
        Integer success = 0;
        Integer all = imeiList.size();
        Integer offLine = 0;
        Integer fail = 0;
        if (stuId == 0) {
            for (String imei : imeiList) {
                if (StringUtils.isBlank(imei)) {
                    fail++;
                    continue;
                }
                String commandNumber = getCurTime();
                boolean isOnline = deviceOnline(imei);
                if (isOnline) {
                    //设备在线则进行指令下发
                    boolean b = commandSendUtils.queryDeviceLocation(imei, commandNumber, Constants.WX_COMMAND_USER_ID, isOnline, false);
                    if (b) {
                        success++;
                        continue;
                    }
                    fail++;
                    continue;
                }
                offLine++;
                continue;
            }
            logger.info("/immediatelyLocation:all = {} ,success= {},offLine = {},fail = {}", all.toString(), success.toString(), offLine.toString(), fail.toString());
            return new RespEntity(RespCode.SUCCESS);
        } else {
            String imei = imeiList.get(0);
            String commandNumber = getCurTime();
            boolean isOnline = deviceOnline(imei);
            if (isOnline) {
                //设备在线则进行指令下发
                boolean b = commandSendUtils.queryDeviceLocation(imei, commandNumber, Constants.WX_COMMAND_USER_ID, isOnline, false);
                if (b) {
                    return new RespEntity(RespCode.SUCCESS);
                }
                return new RespEntity(RespCode.FAILED);
            }
            return new RespEntity(RespCode.DEVICE_OFF_LINE);
        }
    }








    /**
     * 判断设备是否在线
     *
     * @param imei 设备imei号
     * @return 设备是否在线
     */
    public boolean deviceOnline(String imei) {
        boolean isOnline = redisService.hasKey(Constants.DEVICE_ONLINE_PREFIX + imei);
        logger.info("设备:【{}】: {}", imei, isOnline ? "在线" : "离线");
        return isOnline;
    }











    /**
     * 获取用户id
     *
     * @param request
     * @return
     */
    public Integer getUserId(HttpServletRequest request) {
        //获取用户id
        String token = request.getHeader(Constant.HEADER_TOKEN_KEY);
        if (token.equals("aaab")) {
            return 3;
        }
        String redisUserId = redisService.getValue(token);
        if (StringUtils.isBlank(redisUserId)) {
            return 0;
        }
        Integer userId = Integer.parseInt(redisUserId);
        return userId;
    }


    /**
     * 获取当前时间的时分秒（HHmmss）
     *
     * @return
     */
    public String getCurTime() {
        Date d = new Date();
        SimpleDateFormat sbf = new SimpleDateFormat("HH:mm:ss");
        String format = sbf.format(d);
        String[] split = format.split(":");
        String time = split[0].concat(split[1]).concat(split[2]);
        return time;
    }



}
